/*
#    Copyright By Schips, All Rights Reserved
#    https://gitee.com/schips/
#
#    File Name:  xxtea_demo.c
#    Created  :  Wed 23 Oct 2019 02:00:59 PM CST
*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "xxtea.h"

// 加解密密钥，为4个32位无符号整数，即密钥长度为128位  
unsigned int const key[4]= {1,2,3,4};  


int btea_encrypt_file(const char* raw_file, const char * encryptted_file)
{
    // 读写文件有关
    int fd_r, fd_w;
	ssize_t rd_size, wr_size;
    unsigned char buffer[4*1024]; // 设计一个对象池
	unsigned char *poffs;

    // 加密有关
    // v为要加密的数据是两个32位无符号整数  
    unsigned int *v= (unsigned int *)buffer; 
    // 加解密密钥，为4个32位无符号整数，即密钥长度为128位  
    //crypt_len的绝对值表示v的长度，取正表示加密，取负表示解密  
    int crypt_len; 
    

    if(NULL == raw_file)        { return -1; }
    if(NULL == encryptted_file) { return -1; }

    fd_r = open(raw_file, O_RDONLY);
    fd_w = open(encryptted_file, O_WRONLY|O_CREAT|O_TRUNC, 
        S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
    if(fd_r == -1 )  {  return -1;  }
    if(fd_w == -1)   {  close(fd_r); return -1; }

	while(1)
	{
		rd_size = read(fd_r, buffer, sizeof(buffer));
		if(rd_size == -1)
		{
			// CPERROR(CP, "read file error\n");
			goto err;
		}

		if(rd_size == 0)
			break;
	    poffs = buffer;
        crypt_len = rd_size / (sizeof(int)/sizeof(char));
        btea(v, crypt_len, key); 

		while(1)
		{
			wr_size = write(fd_w, poffs, rd_size); // 实际写入长度wr_size 只会小于或等于预设写入长度rd_size
			if(wr_size == -1)
			{
				// CPERROR(CP, "write to new file error\n");
				goto err;
			}
			// 当 实际写入长度 小于 预设写入长度，必须进行处理，以防丢包
			if(wr_size == rd_size) { break; }
            
			rd_size  -=  wr_size;
			poffs +=  wr_size;

		}	
	}

	close(fd_w);
	close(fd_r);
    return 0;
err:
	return -1;
}


int btea_decrypt_file(const char* encryptted_file, const char * raw_file_out)
{
    // 读写文件有关
    int fd_r, fd_w;
	ssize_t rd_size, wr_size;
    unsigned char buffer[4*1024]; // 设计一个对象池
	unsigned char *poffs;
    // 加密有关
    // v为要加密的数据是两个32位无符号整数  
    unsigned int *v= (unsigned int *)buffer; 
    
    //crypt_len的绝对值表示v的长度，取正表示加密，取负表示解密  
    int crypt_len; 

    if(NULL == raw_file_out)    { return -1; }
    if(NULL == encryptted_file) { return -1; }

    fd_r = open(encryptted_file, O_RDONLY);
    fd_w = open(raw_file_out, O_WRONLY|O_CREAT|O_TRUNC, 
        S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
    if(fd_r == -1 )  {  return -1;  }
    if(fd_w == -1)   {  close(fd_r); return -1; }

	while(1)
	{
		rd_size = read(fd_r, buffer, sizeof(buffer));
		if(rd_size == -1)
		{
			// CPERROR(CP, "read file error\n");
			goto err;
		}

		if(rd_size == 0)
			break;
	    poffs = buffer;
        crypt_len = rd_size / (sizeof(int)/sizeof(char));
        btea(v, -crypt_len, key); 

		while(1)
		{
			wr_size = write(fd_w, poffs, rd_size); // 实际写入长度wr_size 只会小于或等于预设写入长度rd_size
			if(wr_size == -1)
			{
				// CPERROR(CP, "write to new file error\n");
				goto err;
			}
			// 当 实际写入长度 小于 预设写入长度，必须进行处理，以防丢包
			if(wr_size == rd_size) { break; }

			rd_size  -=  wr_size;
			poffs +=  wr_size;
		}	
	}

	close(fd_w);
	close(fd_r);
    return 0;
err:
	return -1;
}
  
// for demo
int main()  
{  
    // 加密文件
    btea_encrypt_file("test", "en_test");
    // 解密文件
    btea_decrypt_file("en_test", "de_test");
    return 0;  
} 
